<?php

namespace app\system\controller;

use app\system\exception\CommonException;
use app\system\model\UserModel;
use think\App;
use think\facade\Db;

class Login extends Base
{
    private $userModel;

    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->userModel = new UserModel();
    }


    /**
     *  登录方法
     */
    public function login(): \think\response\Json
    {
        $param = $this->request->param();
        //todo 基本参数校验

        // 检查验证码
        if (false && !captcha_check($param['code'])) {
            //验证失败
            throw new  CommonException('code 不存在', '1');
        };
        $userName = $param['username'];
        $userPassword = $param['password'];
        // 数据库检测账号密码

        $userInfo = $this->userModel->where('user_name', '=', $userName)->find();
        // 1. 查询用户信息,并检查是否符合登录要求
        if(!$userInfo){
            throw new  CommonException('用户不存在', '1');
        }
        if($userInfo['status'] == 1){
            throw new  CommonException('用户停用', '1');
        }elseif($userInfo['status'] == 2){
            throw new  CommonException('用户删除', '1');
        }
        // 2. 用户密码验证  password_verify('admin123', $password);
        if(!password_verify($userPassword, $userInfo['password'])){
            throw new  CommonException('密码错误', '1');
        };
        // 3. 生成token
        $token = signToken($userInfo['user_id']);
        // todo 记录登录日志
        // 组织返回JSON
        $data = [
            'code' => 200,
            'msg' => '操作成功',
            'token' => $token
        ];
        return json($data);

    }

    /**
     * 短信登录（实例）
     */
    public function smsLogin()
    {

    }

    /**
     * 小程序登录（实例）
     */
    public function xcxLogin()
    {

    }

    /**
     * 退出登录
     */
    public function logout(): \think\response\Json
    {
        // 组织返回JSON
        $data = [
            'code' => 200,
            'msg' => '操作成功'
        ];
        return json($data);
    }

    /**
     *  获取用户信息
     */
    public function getInfo(): \think\response\Json
    {
        $param = $this->request->param();
        $uid = $this->request->uid;

        // 组装用户信息
        $sqlUser = 'select u.user_id,
               u.dept_id,
               u.user_name,
               u.nick_name,
               u.user_type,
               u.email,
               u.avatar,
               u.phonenumber,
               u.password,
               u.sex,
               u.status,
               u.del_flag,
               u.login_ip,
               u.login_date,
               u.create_by,
               u.create_time,
               u.remark,
               d.dept_id,
               d.parent_id,
               d.ancestors,
               d.dept_name,
               d.order_num,
               d.leader,
               d.status as dept_status,
               r.role_id,
               r.role_name,
               r.role_key,
               r.role_sort,
               r.data_scope,
               r.status as role_status
        from sys_user u
            left join sys_dept d on u.dept_id = d.dept_id
            left join sys_user_role sur on u.user_id = sur.user_id
            left join sys_role r on r.role_id = sur.role_id
            where u.del_flag = "0" and u.user_id=:uid';
        $arrUser = Db::query($sqlUser, [ 'uid'=> $uid]);
        $value = $arrUser[0];
        $value['dept'] = [
            'deptId'=> $value['dept_id'],
            'parentId'=> $value['parent_id'],
            'ancestors'=> $value['ancestors'],
            'orderNum'=> $value['order_num'],
            'leader'=> $value['leader'],
            'status'=> $value['dept_status'],
        ];
        $value['roles'] = [
            'roleId'=> $value['role_id'],
            'roleName'=> $value['role_name'],
            'roleKey'=> $value['role_key'],
            'roleSort'=> $value['role_sort'],
            'dataScope'=> $value['data_scope'],
            'status'=> $value['role_status'],
        ];
        // 组装角色信息
        if($uid == 1){
            $roles = ['admin'];
        }else{
            $sql = 'select distinct r.role_id as roleId,
                        r.role_name as roleName,
                        r.role_key as roleKey,
                        r.role_sort as roleSort,
                        r.data_scope as dataScope,
                        r.menu_check_strictly as menuCheckStrictly,
                        r.dept_check_strictly as deptCheckStrictly,
                        r.status,
                        r.del_flag as delFlag,
                        r.create_time as createTime,
                        r.remark
        from sys_role r
                 left join sys_user_role sur on sur.role_id = r.role_id
                 left join sys_user u on u.user_id = sur.user_id
                 left join sys_dept d on u.dept_id = d.dept_id
                 WHERE r.del_flag = "0" and sur.user_id = :uid ';
            $arr = Db::query($sql, [ 'uid'=> $uid]);
            $roles = array_unique($arr);
        }

        // 组装权限信息
        if($uid == 1){
            $permissions = ['*:*:*'];
        }else{
            $perSql = 'select distinct m.perms
                    from sys_menu m
                             left join sys_role_menu rm on m.menu_id = rm.menu_id
                             left join sys_user_role sur on rm.role_id = sur.role_id
                             left join sys_role r on r.role_id = sur.role_id
                    where m.status = "0"
                      and r.status = "0"
                      and sur.user_id =:uid';

            $permissions = Db::query($perSql, ['uid'=> $uid]);
        }

        $returnData = [
            'code'=> 200,
            'msg'=> '操作成功',
            'permissions'=> $permissions,
            'roles'=> $roles,
            'user'=> $value
        ];
        return json($returnData);
    }

    /**
     * 获取路由
     */
    public function getRouters(): \think\response\Json
    {
//        $param = $this->request->param();
        $uid = $this->request->uid;
        // 获取登录人的目录
        if($uid == 1){
            $sql = 'SELECT DISTINCT
	m.menu_id as menuId,
	m.parent_id as parentId,
	m.menu_name as menuName,
	m.path,
	m.component,
	m.`query`,
	m.visible,
	m.STATUS,
	ifnull( m.perms, "" ) AS perms,
	m.is_frame as isFrame,
	m.is_cache as isCache,
	m.menu_type as menuType,
	m.icon,
	m.order_num as orderNum,
	m.create_time as createTime
FROM
	sys_menu m 
WHERE
	m.menu_type IN ( "M", "C" ) 
	AND m.STATUS = 0 
ORDER BY
	m.parent_id,
	m.order_num';
            $data = Db::query($sql);
        }else{
            $sql = 'SELECT DISTINCT
	m.menu_id as menuId,
	m.parent_id as parentId,
	m.menu_name as menuName,
	m.path,
	m.component,
	m.`query`,
	m.visible,
	m.STATUS,
	ifnull( m.perms, "" ) AS perms,
	m.is_frame as isFrame,
	m.is_cache as isCache,
	m.menu_type as menuType,
	m.icon,
	m.order_num as orderNum,
	m.create_time as createTime
FROM
	sys_menu m
	LEFT JOIN sys_role_menu rm ON m.menu_id = rm.menu_id
	LEFT JOIN sys_user_role ur ON rm.role_id = ur.role_id
	LEFT JOIN sys_role ro ON ur.role_id = ro.role_id
	LEFT JOIN sys_user u ON ur.user_id = u.user_id 
WHERE
	u.user_id =: uid 
	AND m.menu_type IN ( "M", "C" ) 
	AND m.STATUS = 0 
	AND ro.STATUS = 0 
	AND m.parent_id = 0 
ORDER BY
	m.parent_id,
	m.order_num';
            $data = Db::query($sql, ['uid'=> $uid]);
        }
        $routerData = $this->getChildPerms($data, 0);
        $routers = $this->buildMenus($routerData);

        $returnData = [
            'code'=> 200,
            'msg'=> '操作成功',
            'data'=> $routers
        ];
        return json($returnData);
    }

    /**
     *  根据父节点ID获取所有子节点
     */
    protected function getChildPerms($list, $parentId = 0): array
    {
        $returnList = [];
        foreach ($list as $t){
            if($t['parentId'] == $parentId){
                $t = $this->recursionFn($list, $t);
                $returnList[] = $t;
            }
        }
        return $returnList;
    }

    /**
     * 递归列表 todo
     */
    private function recursionFn($list, &$t)
    {
        $childList = $this->getChildList($list, $t);
        foreach ($childList as &$tChild){
            if($this->hasChild($list, $tChild))
            {
                $this->recursionFn($list, $tChild);
//                $tChild['children'] = $this->getChildList($list, $tChild);
            }
        }
        $t['children'] = $childList;
        return $t;
    }

    /**
     *  查找子节点
     */
    private function getChildList($list, $t): array
    {
        $tlist = [];
        foreach ($list as $n){
            if($n['parentId'] == $t['menuId']){
                $tlist[] = $n;
            }
        }
        return $tlist;
    }

    /**
     *  判断是否有子节点
     */
    private function hasChild($list, $tChild): bool
    {
        return (bool)$this->getChildList($list, $tChild);
    }

    /**
     *
     */
    private function buildMenus(array $routerData): array
    {
        $routers = [];
        foreach ($routerData as $k=> $menu){
            $router = [];
            $router['hidden'] = $menu['visible'] === '1';
            $router['name'] = $this->getRouteName($menu);
            $router['path'] = $this->getRouterPath($menu);
            $router['component'] = $this->getComponent($menu);
            $router['query'] = $menu['query'];
            $router['meta'] = [
                'title'=> $menu['menuName'],
                'icon'=> $menu['icon'],
                'isCache'=> $menu['isCache'] == '1',
                'path'=> $menu['path'],
            ];
            if(strpos($menu['path'],'http') !== false){
                $router['meta']['link'] = $menu['path'];
            }
            if (isset($menu['children']) && count($menu['children']) > 0 && $menu['menuType'] === 'M')
            {
                $cMenus = $menu['children'];
                $router['alwaysShow'] = true;
                $router['redirect'] = "noRedirect";
                $router['children'] = $this->buildMenus($cMenus);
            }elseif ($this->isMenuFrame($menu)){
                $router['meta'] = null;
                $children['path'] = $menu['path'];
                $children['component'] = $menu['component'];
                $children['name'] = Ucfirst($menu['path']);

                $children['meta'] = [
                    'title'=> $menu['menuName'],
                    'icon'=> $menu['icon'],
                    'isCache'=> $menu['is_cache'] == '1',
                    'path'=> $menu['path'],
                ];
                $children['query'] = $menu['query'];
                $childrenList[] = $children;
                $router['children'] = $childrenList;
            }elseif($this->isInnerLink($menu)){
                $router['meta'] = [
                    'title'=> $menu['menuName'],
                    'icon'=> $menu['icon'],
                ];
                $router['path'] = "/";

                $children['path'] = $menu['path'];
                $children['component']  = 'InnerLink';
                $children['name'] = Ucfirst($menu['path']);
                $children['meta'] = [
                    'title'=> $menu['menuName'],
                    'icon'=> $menu['icon'],
                    'path'=> $menu['path'],
                ];
                $childrenList[] = $children;
                $router['children'] = $childrenList;
            }
            $routers[] = $router;
        }
        return $routers;
    }

    private function getRouteName($menu): string
    {

        $routerName = Ucfirst($menu['path']);
        // 非外链并且是一级目录（类型为目录）
        if ($this->isMenuFrame($menu))
        {
            $routerName = "";
        }
        return $routerName;
    }

    private function isMenuFrame($menu): bool
    {
        return $menu['parentId'] == 0 && $menu['menuType'] ==='C' && $menu['isFrame'] === '1';
    }

    /**
     * 获取路由地址
     *
     * @param Menu 菜单信息
     * @return 路由地址
     */
    private function getRouterPath($menu)
    {
        $routerPath = $menu['path'];
        // 内链打开外网方式
        if ($menu['parentId'] != 0 && $this->isInnerLink($menu))
        {
//            $routerPath = innerLinkReplaceEach(routerPath);
        }
        // 非外链并且是一级目录（类型为目录）
        if ($menu['parentId'] == 0 && 'M'== $menu['menuType'] && '1' == $menu['isFrame'])
        {
            $routerPath = "/" . $menu['path'];
        }
        // 非外链并且是一级目录（类型为菜单）
        else if ($this->isMenuFrame($menu))
        {
            $routerPath = "/";
        }
        return $routerPath;
    }


    /**
     * 是否为内链组件
     */
    private function isInnerLink($menu): bool
    {
        return $menu['isFrame'] == '1' && strpos($menu['path'], 'http') !== false;
    }

    /**
     * 获取组件信息
     *
     * @param Menu 菜单信息
     * @return 组件信息
     */
    private function getComponent($menu)
    {
        $component = 'Layout';
        if ($menu['component'] && !$this->isMenuFrame($menu))
        {
            $component = $menu['component'];
        }
        else if (!$menu['component'] && $menu['parentId'] != 0 && $this->isInnerLink($menu))
        {
            $component = "InnerLink";
        }
        else if (!$menu['component']  && $this->isParentView($menu))
        {
            $component = "ParentView";
        }
        return $component;
    }


    /**
     * 是否为parent_view组件
     *
     * @param Menu 菜单信息
     * @return 结果
     */
    private function isParentView($menu): bool
    {
        return $menu['menuType'] == 'M' && $menu['parentId'] != 0;
    }

}
